export const questionsData = [
  // Vue.js 面试题
  {
    id: 'vue-001',
    category: 'vue',
    title: 'Vue 3 Composition API 与 Options API 的区别',
    difficulty: '中级',
    tags: ['Vue3', 'Composition API', 'Options API'],
    content: `
      Vue 3 引入了 Composition API 作为 Options API 的补充。请详细说明：
      1. 两种 API 的主要区别
      2. Composition API 的优势
      3. 什么时候应该使用 Composition API
    `,
    code: `// Options API
export default {
  data() {
    return {
      count: 0,
      name: ''
    }
  },
  methods: {
    increment() {
      this.count++
    }
  },
  computed: {
    displayName() {
      return \`Hello \${this.name}\`
    }
  }
}

// Composition API
import { ref, computed } from 'vue'

export default {
  setup() {
    const count = ref(0)
    const name = ref('')
    
    const increment = () => {
      count.value++
    }
    
    const displayName = computed(() => {
      return \`Hello \${name.value}\`
    })
    
    return {
      count,
      name,
      increment,
      displayName
    }
  }
}`,
    answer: `
      **主要区别：**
      
      1. **代码组织方式**：
         - Options API：按选项类型组织（data、methods、computed等）
         - Composition API：按功能逻辑组织
      
      2. **类型推断**：
         - Composition API 对 TypeScript 支持更好
         - 可以获得更好的 IDE 智能提示
      
      3. **逻辑复用**：
         - Composition API 通过组合函数更容易复用逻辑
         - Options API 需要通过 mixins，容易产生命名冲突
      
      **Composition API 优势：**
      - 更好的逻辑复用和组织
      - 更小的打包体积（tree-shaking）
      - 更好的 TypeScript 支持
      - 更灵活的代码组织
      
      **使用场景：**
      - 复杂组件推荐使用 Composition API
      - 简单组件可以继续使用 Options API
      - 需要逻辑复用时优先选择 Composition API
    `,
    tips: '在学习 Composition API 时，重点理解响应式原理和组合函数的概念。',
    favorite: false
  },
  {
    id: 'vue-002',
    category: 'vue',
    title: 'Vue 响应式原理详解',
    difficulty: '高级',
    tags: ['响应式', 'Proxy', 'Observer'],
    content: `
      请详细解释 Vue 的响应式原理：
      1. Vue 2 和 Vue 3 的响应式实现差异
      2. 响应式数据的依赖收集过程
      3. 如何触发视图更新
    `,
    code: `// Vue 3 响应式示例
import { reactive, effect, ref } from 'vue'

// 创建响应式对象
const state = reactive({
  count: 0,
  name: 'Vue'
})

// 创建响应式引用
const message = ref('Hello')

// 副作用函数
effect(() => {
  console.log(\`Count: \${state.count}\`)
  console.log(\`Message: \${message.value}\`)
})

// 修改数据会自动触发副作用函数
state.count++ // 输出: Count: 1
message.value = 'Hi' // 输出: Message: Hi`,
    answer: `
      **Vue 2 vs Vue 3 响应式实现：**
      
      **Vue 2 (Object.defineProperty)：**
      - 只能劫持对象的属性
      - 无法检测数组索引和长度变化
      - 需要递归遍历对象的所有属性
      
      **Vue 3 (Proxy)：**
      - 可以劫持整个对象
      - 支持数组、Map、Set 等数据结构
      - 懒代理，只有访问时才创建代理
      
      **依赖收集过程：**
      1. 渲染函数执行时触发 getter
      2. Dep 收集当前的 Watcher
      3. 数据变化时触发 setter
      4. 通知所有相关的 Watcher 更新
      
      **视图更新机制：**
      1. 数据变化触发 setter
      2. 调度器异步批量更新
      3. 执行组件的渲染函数
      4. 虚拟 DOM 比较和更新真实 DOM
    `,
    tips: '理解响应式原理有助于调试和性能优化，建议深入学习 Proxy 和 Reflect API。',
    favorite: true
  },
  {
    id: 'vue-003',
    category: 'vue',
    title: 'Vue Router 路由守卫的执行顺序',
    difficulty: '中级',
    tags: ['Vue Router', '路由守卫', '导航'],
    content: `
      请详细说明 Vue Router 中各种路由守卫的执行顺序，并解释每种守卫的作用场景。
    `,
    code: `// 全局前置守卫
router.beforeEach((to, from, next) => {
  console.log('全局前置守卫')
  next()
})

// 全局解析守卫
router.beforeResolve((to, from, next) => {
  console.log('全局解析守卫')
  next()
})

// 全局后置钩子
router.afterEach((to, from) => {
  console.log('全局后置钩子')
})

// 路由独享守卫
const routes = [
  {
    path: '/user',
    component: User,
    beforeEnter: (to, from, next) => {
      console.log('路由独享守卫')
      next()
    }
  }
]

// 组件内守卫
export default {
  beforeRouteEnter(to, from, next) {
    console.log('组件内前置守卫')
    next()
  },
  beforeRouteUpdate(to, from, next) {
    console.log('组件内更新守卫')
    next()
  },
  beforeRouteLeave(to, from, next) {
    console.log('组件内离开守卫')
    next()
  }
}`,
    answer: `
      **完整的导航解析流程：**
      
      1. **导航被触发**
      2. **在失活的组件里调用 beforeRouteLeave 守卫**
      3. **调用全局的 beforeEach 守卫**
      4. **在重用的组件里调用 beforeRouteUpdate 守卫**
      5. **在路由配置里调用 beforeEnter**
      6. **解析异步路由组件**
      7. **在被激活的组件里调用 beforeRouteEnter**
      8. **调用全局的 beforeResolve 守卫**
      9. **导航被确认**
      10. **调用全局的 afterEach 钩子**
      11. **触发 DOM 更新**
      12. **调用 beforeRouteEnter 守卫中传给 next 的回调函数**
      
      **使用场景：**
      - **beforeEach**: 权限验证、登录检查
      - **beforeResolve**: 获取数据、确保导航完成前的准备工作
      - **afterEach**: 页面埋点、修改页面标题
      - **beforeRouteLeave**: 未保存提醒、清理工作
      - **beforeRouteEnter**: 组件初始化前的逻辑
      - **beforeRouteUpdate**: 路由参数变化时的处理
    `,
    tips: '记住执行顺序的关键是理解 "离开 -> 进入 -> 确认" 的流程。',
    favorite: false
  },

  // JavaScript 面试题
  {
    id: 'js-001',
    category: 'javascript',
    title: 'Event Loop 事件循环机制',
    difficulty: '高级',
    tags: ['Event Loop', '异步', '宏任务', '微任务'],
    content: `
      请详细解释 JavaScript 的事件循环机制：
      1. 宏任务和微任务的区别
      2. 执行栈、任务队列的关系
      3. 分析下面代码的执行顺序
    `,
    code: `console.log('1')

setTimeout(() => {
  console.log('2')
  Promise.resolve().then(() => {
    console.log('3')
  })
}, 0)

Promise.resolve().then(() => {
  console.log('4')
  setTimeout(() => {
    console.log('5')
  }, 0)
})

console.log('6')

// 输出顺序是什么？`,
    answer: `
      **执行顺序：1 -> 6 -> 4 -> 2 -> 3 -> 5**
      
      **详细分析：**
      
      1. **同步代码执行**：
         - 输出 '1'
         - setTimeout 加入宏任务队列
         - Promise.then 加入微任务队列
         - 输出 '6'
      
      2. **第一轮微任务**：
         - 执行 Promise.then，输出 '4'
         - 新的 setTimeout 加入宏任务队列
      
      3. **第一个宏任务**：
         - 执行第一个 setTimeout，输出 '2'
         - Promise.then 加入微任务队列
      
      4. **第二轮微任务**：
         - 输出 '3'
      
      5. **第二个宏任务**：
         - 输出 '5'
      
      **核心概念：**
      - **宏任务**: setTimeout, setInterval, I/O, UI渲染
      - **微任务**: Promise.then, async/await, queueMicrotask
      - **执行规则**: 每执行完一个宏任务，就会清空所有微任务
    `,
    tips: '记住口诀：同步 -> 微任务 -> 宏任务，每个宏任务执行后都要清空微任务队列。',
    favorite: true
  },
  {
    id: 'js-002',
    category: 'javascript',
    title: '闭包的原理和应用场景',
    difficulty: '中级',
    tags: ['闭包', '作用域', '内存'],
    content: `
      请详细解释闭包的概念，并说明：
      1. 闭包的形成条件
      2. 闭包的应用场景
      3. 闭包可能带来的问题
    `,
    code: `// 经典闭包示例
function createCounter() {
  let count = 0
  
  return function() {
    return ++count
  }
}

const counter1 = createCounter()
const counter2 = createCounter()

console.log(counter1()) // ?
console.log(counter1()) // ?
console.log(counter2()) // ?

// 循环中的闭包问题
for (var i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i) // ?
  }, 100)
}

// 解决方案
for (let i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i) // ?
  }, 100)
}`,
    answer: `
      **闭包定义：** 函数和其词法环境的组合，使得函数可以访问其外部作用域的变量。
      
      **形成条件：**
      1. 函数嵌套
      2. 内层函数引用外层函数的变量
      3. 外层函数返回内层函数
      
      **代码分析：**
      - counter1(): 1, 2  (每个闭包维护独立的count)
      - counter2(): 1     (独立的计数器)
      - 第一个循环: 3, 3, 3 (var 作用域问题)
      - 第二个循环: 0, 1, 2 (let 块级作用域)
      
      **应用场景：**
      1. **模块模式**: 创建私有变量
      2. **函数柯里化**: 参数复用
      3. **回调函数**: 保持状态
      4. **防抖节流**: 维护定时器状态
      
      **潜在问题：**
      - 内存泄漏（变量无法被回收）
      - 性能影响（额外的作用域链查找）
      
      **最佳实践：**
      - 及时清理不需要的闭包
      - 避免在循环中创建闭包
      - 使用 WeakMap 存储私有数据
    `,
    tips: '理解闭包的关键是掌握作用域链和执行上下文的概念。',
    favorite: false
  },
  {
    id: 'js-003',
    category: 'javascript',
    title: 'Promise 和 async/await 的区别',
    difficulty: '中级',
    tags: ['Promise', 'async/await', '异步编程'],
    content: `
      请比较 Promise 和 async/await 的异同点：
      1. 语法差异
      2. 错误处理方式
      3. 并发处理能力
    `,
    code: `// Promise 方式
function fetchUserData() {
  return fetch('/api/user')
    .then(response => response.json())
    .then(user => {
      return fetch(\`/api/posts/\${user.id}\`)
    })
    .then(response => response.json())
    .catch(error => {
      console.error('Error:', error)
    })
}

// async/await 方式
async function fetchUserDataAsync() {
  try {
    const userResponse = await fetch('/api/user')
    const user = await userResponse.json()
    
    const postsResponse = await fetch(\`/api/posts/\${user.id}\`)
    const posts = await postsResponse.json()
    
    return posts
  } catch (error) {
    console.error('Error:', error)
  }
}

// 并发处理
// Promise.all
Promise.all([
  fetch('/api/users'),
  fetch('/api/posts'),
  fetch('/api/comments')
]).then(responses => {
  // 处理结果
})

// async/await 并发
async function fetchAllData() {
  const [users, posts, comments] = await Promise.all([
    fetch('/api/users'),
    fetch('/api/posts'),
    fetch('/api/comments')
  ])
  
  return { users, posts, comments }
}`,
    answer: `
      **语法差异：**
      
      **Promise：**
      - 链式调用 .then()
      - 回调函数形式
      - 需要显式返回 Promise
      
      **async/await：**
      - 同步代码风格
      - 使用 try/catch 处理错误
      - 自动包装返回值为 Promise
      
      **错误处理：**
      
      **Promise：**
      - 使用 .catch() 捕获错误
      - 错误会沿着链条传播
      - 需要在每个 .then() 中处理可能的错误
      
      **async/await：**
      - 使用 try/catch 统一处理
      - 更接近同步代码的错误处理方式
      - 可以精确定位错误发生的位置
      
      **并发处理：**
      
      **相同点：**
      - 都可以配合 Promise.all 实现并发
      - 本质上 async/await 是 Promise 的语法糖
      
      **差异：**
      - async/await 顺序执行，Promise 可以更灵活
      - Promise 可以更容易实现复杂的异步流程控制
      
      **选择建议：**
      - 简单异步操作：async/await
      - 复杂异步流程：Promise
      - 并发操作：两者配合使用
    `,
    tips: 'async/await 不能完全替代 Promise，理解两者的适用场景很重要。',
    favorite: false
  },

  // CSS 面试题
  {
    id: 'css-001',
    category: 'css',
    title: 'Flexbox 布局原理和应用',
    difficulty: '中级',
    tags: ['Flexbox', '布局', '响应式'],
    content: `
      请详细解释 Flexbox 布局：
      1. 主轴和交叉轴的概念
      2. 常用属性的作用
      3. 实现常见布局需求
    `,
    code: `.container {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
}

.item {
  flex: 1 1 auto;
  /* flex-grow: 1; */
  /* flex-shrink: 1; */
  /* flex-basis: auto; */
}

/* 三栏布局示例 */
.layout {
  display: flex;
  min-height: 100vh;
}

.sidebar {
  flex: 0 0 200px; /* 固定宽度 */
  background: #f0f0f0;
}

.main {
  flex: 1; /* 填充剩余空间 */
  padding: 20px;
}

.aside {
  flex: 0 0 150px; /* 固定宽度 */
  background: #e0e0e0;
}`,
    answer: `
      **核心概念：**
      
      **主轴 (Main Axis):**
      - flex-direction 定义的方向
      - row: 水平方向, column: 垂直方向
      - justify-content 控制主轴对齐
      
      **交叉轴 (Cross Axis):**
      - 垂直于主轴的方向
      - align-items 控制交叉轴对齐
      
      **容器属性：**
      - **flex-direction**: 主轴方向
      - **justify-content**: 主轴对齐方式
      - **align-items**: 交叉轴对齐方式
      - **flex-wrap**: 是否换行
      - **align-content**: 多行对齐方式
      
      **项目属性：**
      - **flex-grow**: 放大比例
      - **flex-shrink**: 缩小比例
      - **flex-basis**: 基础大小
      - **align-self**: 单独对齐方式
      
      **常见布局：**
      
      **水平垂直居中：**
      \`\`\`css
      .center {
        display: flex;
        justify-content: center;
        align-items: center;
      }
      \`\`\`
      
      **等高列布局：**
      \`\`\`css
      .columns {
        display: flex;
      }
      .column {
        flex: 1;
      }
      \`\`\`
      
      **底部固定布局：**
      \`\`\`css
      .page {
        display: flex;
        flex-direction: column;
        min-height: 100vh;
      }
      .footer {
        margin-top: auto;
      }
      \`\`\`
    `,
    tips: 'Flexbox 适合一维布局，Grid 适合二维布局。记住主轴和交叉轴的概念是关键。',
    favorite: true
  },
  {
    id: 'css-002',
    category: 'css',
    title: 'CSS Grid 网格布局详解',
    difficulty: '高级',
    tags: ['Grid', '网格布局', '二维布局'],
    content: `
      请详细说明 CSS Grid 的使用方法：
      1. 网格容器和网格项的概念
      2. 网格线、网格轨道、网格区域
      3. 如何实现复杂的网页布局
    `,
    code: `.grid-container {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas: 
    "header header header"
    "sidebar main aside"
    "footer footer footer";
  gap: 20px;
  min-height: 100vh;
}

.header {
  grid-area: header;
  background: #333;
  color: white;
}

.sidebar {
  grid-area: sidebar;
  background: #f0f0f0;
}

.main {
  grid-area: main;
  background: white;
}

.aside {
  grid-area: aside;
  background: #e0e0e0;
}

.footer {
  grid-area: footer;
  background: #333;
  color: white;
}

/* 响应式网格 */
@media (max-width: 768px) {
  .grid-container {
    grid-template-areas: 
      "header"
      "main"
      "sidebar"
      "aside"
      "footer";
    grid-template-columns: 1fr;
  }
}`,
    answer: `
      **核心概念：**
      
      **网格容器 (Grid Container):**
      - 设置 display: grid 的元素
      - 定义网格的结构和属性
      
      **网格项 (Grid Item):**
      - 网格容器的直接子元素
      - 可以放置在网格中的任意位置
      
      **网格术语：**
      - **网格线 (Grid Line)**: 分隔网格的线条
      - **网格轨道 (Grid Track)**: 相邻网格线之间的空间
      - **网格区域 (Grid Area)**: 网格单元的矩形区域
      
      **容器属性：**
      
      **定义网格结构：**
      - \`grid-template-columns\`: 列的大小和数量
      - \`grid-template-rows\`: 行的大小和数量
      - \`grid-template-areas\`: 命名网格区域
      
      **对齐和间距：**
      - \`gap\`: 网格间距
      - \`justify-items\`: 水平对齐
      - \`align-items\`: 垂直对齐
      
      **项目属性：**
      - \`grid-column\`: 列位置
      - \`grid-row\`: 行位置
      - \`grid-area\`: 指定区域
      
      **单位和函数：**
      - \`fr\`: 可用空间的分数
      - \`repeat()\`: 重复模式
      - \`minmax()\`: 最小最大值
      - \`auto-fit/auto-fill\`: 自动调整
      
      **优势：**
      - 二维布局控制
      - 精确的元素定位
      - 响应式设计友好
      - 减少媒体查询需求
    `,
    tips: 'Grid 比 Flexbox 更适合复杂的二维布局，两者可以很好地配合使用。',
    favorite: false
  },
  {
    id: 'css-003',
    category: 'css',
    title: 'CSS 选择器优先级和权重计算',
    difficulty: '初级',
    tags: ['选择器', '优先级', '权重'],
    content: `
      请解释 CSS 选择器的优先级规则：
      1. 不同类型选择器的权重
      2. 权重的计算方法
      3. 如何避免优先级冲突
    `,
    code: `/* 不同选择器示例 */
* { color: black; }                    /* 通配符选择器 */
p { color: blue; }                     /* 元素选择器 */
.text { color: green; }                /* 类选择器 */
#title { color: red; }                 /* ID选择器 */
p.text { color: purple; }              /* 元素+类选择器 */
div p.text { color: orange; }          /* 后代选择器 */
p[data-type="text"] { color: yellow; } /* 属性选择器 */

/* 内联样式 */
<p style="color: pink;">文本</p>

/* !important */
.text { color: brown !important; }

/* 问题：下面的p元素最终是什么颜色？ */
<div>
  <p id="title" class="text" data-type="text" style="color: pink;">
    Hello World
  </p>
</div>`,
    answer: `
      **权重计算规则 (从高到低)：**
      
      1. **内联样式**: 1000
      2. **ID选择器**: 100
      3. **类选择器、属性选择器、伪类**: 10
      4. **元素选择器、伪元素**: 1
      5. **通配符选择器**: 0
      
      **具体计算：**
      - \`*\`: 0
      - \`p\`: 1
      - \`.text\`: 10
      - \`#title\`: 100
      - \`p.text\`: 1 + 10 = 11
      - \`div p.text\`: 1 + 1 + 10 = 12
      - \`p[data-type="text"]\`: 1 + 10 = 11
      - 内联样式: 1000
      
      **优先级顺序：**
      1. **!important** (最高优先级)
      2. **内联样式** (1000)
      3. **ID选择器** (100)
      4. **类/属性/伪类选择器** (10)
      5. **元素/伪元素选择器** (1)
      
      **示例分析：**
      如果没有 !important，最终颜色是 **pink** (内联样式)
      如果有 !important，则是 **brown**
      
      **最佳实践：**
      - 避免使用 !important
      - 保持选择器简洁
      - 使用 CSS 模块化方案
      - 利用层叠顺序而非高权重
      
      **避免冲突的方法：**
      - 使用 CSS-in-JS
      - BEM 命名规范
      - CSS Modules
      - Styled Components
    `,
    tips: '记住权重计算公式：内联样式(1000) > ID(100) > 类(10) > 元素(1)，!important 优先级最高。',
    favorite: false
  },

  // JavaScript 原型链面试题
  {
    id: 'js-proto-001',
    category: 'javascript',
    title: 'JavaScript 原型链与继承机制',
    difficulty: '中级',
    tags: ['原型链', 'prototype', '__proto__', '继承'],
    content: `
      请详细解释 JavaScript 中的原型链和继承机制：
      1. prototype 和 __proto__ 的区别和关系
      2. 原型链如何实现继承
      3. instanceof 运算符的工作原理
    `,
    code: `// 构造函数
function Person(name) {
  this.name = name;
}

// 原型方法
Person.prototype.sayHello = function() {
  console.log(\`Hello, I'm \${this.name}\`);
};

// 创建实例
const alice = new Person('Alice');

// 原型链验证
console.log(alice.__proto__ === Person.prototype);       // true
console.log(Person.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__ === null);        // true

// instanceof 检查
console.log(alice instanceof Person);  // true
console.log(alice instanceof Object);  // true`,
    answer: `
      **prototype 和 __proto__ 的区别和关系：**
      
      1. **prototype**：
         - 是函数特有的属性
         - 当函数作为构造函数使用时，它的 prototype 属性会成为新创建对象的原型
         - 用于存放实例共享的属性和方法
      
      2. **__proto__**：
         - 是每个对象都有的内部属性
         - 指向创建该对象的构造函数的 prototype
         - 是对象访问其原型链的入口
         - 现代 JavaScript 推荐使用 Object.getPrototypeOf() 代替直接访问 __proto__
      
      3. **关键关系**：
         - instance.__proto__ === Constructor.prototype
         - Constructor.prototype.constructor === Constructor
      
      **原型链实现继承：**
      
      1. JavaScript 通过原型链实现继承
      2. 当访问对象的属性时，如果对象本身没有该属性，则会沿着 __proto__ 向上查找
      3. 这个查找过程会一直持续到找到属性或到达原型链末端 (null)
      
      **instanceof 运算符原理：**
      
      1. instanceof 检查右侧构造函数的 prototype 是否出现在左侧对象的原型链上
      2. 算法本质：循环检查 obj.__proto__ 是否等于 Constructor.prototype
      3. 如果找到匹配则返回 true，如果到达原型链末端仍未找到则返回 false
    `,
    tips: '理解原型链对于掌握 JavaScript 面向对象编程至关重要，建议结合实际代码练习加深理解。',
    favorite: false
  },
  {
    id: 'js-proto-002',
    category: 'javascript',
    title: '实现继承的多种方式及优缺点',
    difficulty: '高级',
    tags: ['继承', '原型链', '构造函数', 'class'],
    content: `
      JavaScript 中实现继承有多种方式，请详细说明以下几种继承方式的实现原理、优缺点及适用场景：
      1. 原型链继承
      2. 构造函数继承
      3. 组合继承
      4. 原型式继承
      5. 寄生式继承
      6. 寄生组合式继承
      7. ES6 class 继承
    `,
    code: `// 原型链继承
function Animal(name) {
  this.name = name;
  this.colors = ['black', 'white'];
}
Animal.prototype.getInfo = function() {
  return this.name;
};

function Dog(age) {
  this.age = age;
}
// 原型链继承的核心
Dog.prototype = new Animal('旺财');
const dog = new Dog(2);

// ES6 class 继承
class Animal {
  constructor(name) {
    this.name = name;
    this.colors = ['black', 'white'];
  }
  getInfo() {
    return this.name;
  }
}

class Dog extends Animal {
  constructor(name, age) {
    super(name);
    this.age = age;
  }
  bark() {
    console.log('Woof!');
  }
}
const dog = new Dog('旺财', 2);`,
    answer: `
      **1. 原型链继承**
      
      **原理**：子类构造函数的原型指向父类实例
      
      **优点**：
      - 简单易实现
      - 可继承父类原型上的属性和方法
      
      **缺点**：
      - 引用类型属性会被所有实例共享
      - 无法向父类构造函数传参
      
      **2. 构造函数继承**
      
      **原理**：在子类构造函数中调用父类构造函数
      
      **优点**：
      - 可以向父类传参
      - 避免引用类型属性被共享
      
      **缺点**：
      - 无法继承父类原型上的属性和方法
      - 每个实例都会创建父类方法副本，浪费内存
      
      **3. 组合继承**
      
      **原理**：结合原型链继承和构造函数继承
      
      **优点**：
      - 可以继承父类原型上的属性和方法
      - 可以向父类传参
      - 避免引用类型属性被共享
      
      **缺点**：
      - 父类构造函数被调用两次
      - 存在内存冗余
      
      **4. 原型式继承**
      
      **原理**：利用空对象作为中介，复制一个对象的属性
      
      **优点**：
      - 不需要构造函数
      
      **缺点**：
      - 引用类型属性会被所有实例共享
      
      **5. 寄生式继承**
      
      **原理**：在原型式继承基础上增强对象
      
      **优点**：
      - 可以增强对象
      
      **缺点**：
      - 同原型式继承
      - 难以复用
      
      **6. 寄生组合式继承**
      
      **原理**：通过寄生方式继承父类原型，再将结果指定为子类原型
      
      **优点**：
      - 只调用一次父类构造函数
      - 避免在子类原型上创建不必要属性
      - 原型链保持不变
      
      **缺点**：
      - 实现较复杂
      
      **7. ES6 class 继承**
      
      **原理**：基于原型机制的语法糖，内部使用寄生组合式继承
      
      **优点**：
      - 语法简洁清晰
      - 实现了真正的继承关系
      - 有完整的类特性（super、静态方法等）
      
      **缺点**：
      - 不支持多继承
    `,
    tips: '寄生组合式继承是最理想的继承方式，而ES6的class继承是其语法糖，推荐在现代项目中使用。',
    favorite: false
  },
  {
    id: 'js-proto-003',
    category: 'javascript',
    title: '手写实现 new 操作符',
    difficulty: '中级',
    tags: ['new', '原型', '构造函数'],
    content: `
      请手写实现一个 myNew 函数，模拟 JavaScript 中 new 操作符的功能。
      需要实现以下功能：
      1. 创建一个新对象
      2. 将新对象的 __proto__ 指向构造函数的 prototype
      3. 将构造函数的 this 指向新对象
      4. 如果构造函数返回对象则使用该返回值，否则返回新创建的对象
    `,
    code: `function myNew(constructor, ...args) {
  // 请实现此函数
}

// 测试用例
function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.sayHello = function() {
  console.log(\`Hello, I'm \${this.name}\`);
};

const person = myNew(Person, 'Alice', 25);
console.log(person.name); // 应输出: Alice
console.log(person.age);  // 应输出: 25
person.sayHello();       // 应输出: Hello, I'm Alice
console.log(person instanceof Person); // 应输出: true`,
    answer: `
      **手写实现 new 操作符：**
      
      \`\`\`javascript
      function myNew(constructor, ...args) {
        // 1. 创建一个新对象，将其 __proto__ 指向构造函数的 prototype
        const obj = Object.create(constructor.prototype);
        
        // 2. 将构造函数的 this 指向新对象并执行
        const result = constructor.apply(obj, args);
        
        // 3. 如果构造函数返回对象则使用该返回值，否则返回新创建的对象
        return (typeof result === 'object' && result !== null) ? result : obj;
      }
      \`\`\`
      
      **实现步骤解析：**
      
      1. **创建新对象**：使用 Object.create() 创建一个新对象，并将其原型指向构造函数的 prototype
      
      2. **执行构造函数**：使用 apply() 调用构造函数，将 this 指向新创建的对象，并传入参数
      
      3. **处理返回值**：
         - 如果构造函数返回的是对象，则返回该对象
         - 如果构造函数没有返回值或返回的是原始类型，则返回新创建的对象
      
      **new 操作符的本质**：
      - 创建原型链关系（实例与构造函数的连接）
      - 初始化对象（执行构造函数）
      - 返回合适的对象
    `,
    tips: '理解 new 操作符的原理有助于深入理解 JavaScript 的对象创建和继承机制。',
    favorite: false
  },
  {
    id: 'js-proto-004',
    category: 'javascript',
    title: '实现对象的深拷贝',
    difficulty: '中级',
    tags: ['深拷贝', '浅拷贝', '原型'],
    content: `
      请实现一个深拷贝函数 deepClone，要求：
      1. 能够正确处理基本数据类型
      2. 能够处理引用类型（对象、数组等）
      3. 处理循环引用问题
      4. 保持原型链
      5. 处理特殊对象（Date、RegExp等）
    `,
    code: `function deepClone(obj, hash = new WeakMap()) {
  // 请实现此函数
}

// 测试用例
const obj1 = {
  name: 'Alice',
  info: {
    age: 25,
    address: {
      city: 'Shanghai'
    }
  },
  hobbies: ['reading', 'music'],
  date: new Date(),
  regexp: /\\d+/,
  fn: function() { console.log(this.name) }
};

// 循环引用
obj1.self = obj1;

const obj2 = deepClone(obj1);

// 验证是否为深拷贝
obj2.info.age = 30;
obj2.hobbies.push('sports');
console.log(obj1.info.age); // 应输出: 25
console.log(obj1.hobbies.length); // 应输出: 2`,
    answer: `
      **实现对象的深拷贝：**
      
      \`\`\`javascript
      function deepClone(obj, hash = new WeakMap()) {
        // 处理基本类型和 null
        if (obj === null || typeof obj !== 'object') {
          return obj;
        }
        
        // 处理日期对象
        if (obj instanceof Date) {
          return new Date(obj);
        }
        
        // 处理正则对象
        if (obj instanceof RegExp) {
          return new RegExp(obj.source, obj.flags);
        }
        
        // 处理循环引用
        if (hash.has(obj)) {
          return hash.get(obj);
        }
        
        // 获取对象的构造函数，保持原型链
        const constr = obj.constructor;
        
        // 创建新对象，维持原型链
        const clone = Object.create(Object.getPrototypeOf(obj));
        
        // 将当前对象加入 hash，防止循环引用
        hash.set(obj, clone);
        
        // 处理数组
        if (Array.isArray(obj)) {
          clone.length = obj.length;
          for (let i = 0; i < obj.length; i++) {
            clone[i] = deepClone(obj[i], hash);
          }
          return clone;
        }
        
        // 处理普通对象
        // 获取所有属性描述符，包括不可枚举属性
        const allProps = Object.getOwnPropertyDescriptors(obj);
        
        // 复制所有属性描述符到新对象
        Object.defineProperties(clone, Object.fromEntries(
          Object.entries(allProps).map(([key, descriptor]) => {
            if (descriptor.value !== undefined) {
              descriptor.value = deepClone(descriptor.value, hash);
            }
            return [key, descriptor];
          })
        ));
        
        return clone;
      }
      \`\`\`
      
      **实现要点解析：**
      
      1. **处理基本类型**：直接返回
      
      2. **处理特殊对象**：
         - Date：创建新的 Date 对象
         - RegExp：创建新的 RegExp 对象
      
      3. **处理循环引用**：
         - 使用 WeakMap 存储已克隆对象
         - 检查是否已经克隆过该对象
      
      4. **保持原型链**：
         - 使用 Object.create 和 Object.getPrototypeOf 保持原型链
      
      5. **处理对象属性**：
         - 使用 Object.getOwnPropertyDescriptors 获取所有属性描述符
         - 使用 Object.defineProperties 定义新对象的属性
         - 递归处理属性值
      
      6. **处理数组**：
         - 特殊处理数组长度和元素
    `,
    tips: '深拷贝是面试中的常见问题，理解其原理对处理复杂对象操作很有帮助。注意处理循环引用和特殊对象类型。',
    favorite: false
  }
];

// 导出统计信息
export const getStatistics = () => {
  const stats = {
    total: questionsData.length,
    byCategory: {},
    byDifficulty: {},
    favorites: questionsData.filter(q => q.favorite).length
  };
  
  questionsData.forEach(question => {
    // 按分类统计
    stats.byCategory[question.category] = (stats.byCategory[question.category] || 0) + 1;
    
    // 按难度统计
    stats.byDifficulty[question.difficulty] = (stats.byDifficulty[question.difficulty] || 0) + 1;
  });
  
  return stats;
};

// 搜索功能
export const searchQuestions = (query, category = '', difficulty = '') => {
  let filtered = questionsData;
  
  if (category) {
    filtered = filtered.filter(q => q.category === category);
  }
  
  if (difficulty) {
    filtered = filtered.filter(q => q.difficulty === difficulty);
  }
  
  if (query) {
    const searchTerm = query.toLowerCase();
    filtered = filtered.filter(q => 
      q.title.toLowerCase().includes(searchTerm) ||
      q.content.toLowerCase().includes(searchTerm) ||
      q.tags.some(tag => tag.toLowerCase().includes(searchTerm))
    );
  }
  
  return filtered;
}; 